package com.fandou.base.view.recyclerview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.widget.LinearLayout;

import androidx.annotation.NonNull;
import androidx.core.view.ViewCompat;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;

/**
 * DividerItemDecoration is a {@link RecyclerView.ItemDecoration} that can be used as a divider
 * between items of a {@link androidx.recyclerview.widget.LinearLayoutManager}
 * or {@link androidx.recyclerview.widget.GridLayoutManager}. It supports both {@link #HORIZONTAL} and
 * {@link #VERTICAL} orientations.
 * <p>
 * <pre>
 *     mDividerItemDecoration = new BaseDividerItemDecoration(recyclerView.getContext(),
 *             mLayoutManager.getOrientation());
 *     recyclerView.addItemDecoration(mDividerItemDecoration);
 * </pre>
 */
public class BaseDividerItemDecoration extends RecyclerView.ItemDecoration {
	public static final int HORIZONTAL = LinearLayout.HORIZONTAL;
	public static final int VERTICAL = LinearLayout.VERTICAL;

	private static final int[] ATTRS = new int[]{android.R.attr.listDivider};

	private Drawable mHeadDivider;
	private Drawable mFootDivider;
	private Drawable mHorizontalDivider;
	private Drawable mVerticalDivider;

	/**
	 * Current orientation. Either {@link #HORIZONTAL} or {@link #VERTICAL}.
	 */
	private int mOrientation;
	private int spanCount;
	private final Rect mBounds = new Rect();

	/**
	 * Creates a divider {@link RecyclerView.ItemDecoration} that can be used with a
	 * {@link androidx.recyclerview.widget.LinearLayoutManager}
	 * or {@link androidx.recyclerview.widget.GridLayoutManager}.
	 *
	 * @param context     Current context, it will be used to access resources.
	 * @param orientation Divider orientation. Should be {@link #HORIZONTAL} or {@link #VERTICAL}.
	 */
	public BaseDividerItemDecoration(Context context, int orientation) {
		this(context, 1, orientation);
	}

	/**
	 * Creates a divider {@link RecyclerView.ItemDecoration} that can be used with a
	 * {@link androidx.recyclerview.widget.GridLayoutManager}.
	 * @param context     Current context, it will be used to access resources.
	 * @param gridLayoutManager
	 */
	public BaseDividerItemDecoration(Context context, GridLayoutManager gridLayoutManager) {
		this(context, gridLayoutManager.getSpanCount(), gridLayoutManager.getOrientation());
	}

	/**
	 * Creates a divider {@link RecyclerView.ItemDecoration} that can be used with a
	 * {@link androidx.recyclerview.widget.StaggeredGridLayoutManager}.
	 * @param context     Current context, it will be used to access resources.
	 * @param staggeredGridLayoutManager
	 */
	public BaseDividerItemDecoration(Context context, StaggeredGridLayoutManager staggeredGridLayoutManager) {
		this(context, staggeredGridLayoutManager.getSpanCount(), staggeredGridLayoutManager.getOrientation());
	}

	/**
	 * Creates a divider {@link RecyclerView.ItemDecoration} that can be used with a
	 * {@link androidx.recyclerview.widget.LinearLayoutManager}
	 * or {@link androidx.recyclerview.widget.GridLayoutManager}.
	 *
	 * @param context     Current context, it will be used to access resources.
	 * @param spanCount The total number of spans in the grid
	 * @param orientation Divider orientation. Should be {@link #HORIZONTAL} or {@link #VERTICAL}.
	 */
	public BaseDividerItemDecoration(Context context, int spanCount, int orientation) {
		final TypedArray a = context.obtainStyledAttributes(ATTRS);
		mHorizontalDivider = a.getDrawable(0);
		mVerticalDivider = a.getDrawable(0);
		a.recycle();
		setOrientation(orientation);
		setSpanCount(spanCount);
	}

	/**
	 * Sets the orientation for this divider. This should be called if
	 * {@link RecyclerView.LayoutManager} changes orientation.
	 *
	 * @param orientation {@link #HORIZONTAL} or {@link #VERTICAL}
	 */
	public void setOrientation(int orientation) {
		if (orientation != HORIZONTAL && orientation != VERTICAL) {
			throw new IllegalArgumentException(
					"Invalid orientation. It should be either HORIZONTAL or VERTICAL");
		}
		mOrientation = orientation;
	}

	/**
	 * Sets the {@link Drawable} for the divider of head.
	 *
	 * @param drawable Drawable that should be used as a divider.
	 */
	public void setHeadDrawable(@NonNull Drawable drawable) {
		if (drawable == null) {
			throw new IllegalArgumentException("Drawable cannot be null.");
		}
		mHeadDivider = drawable;
	}

	/**
	 * Sets the {@link Drawable} for the divider of foot.
	 *
	 * @param drawable Drawable that should be used as a divider.
	 */
	public void setFootDrawable(@NonNull Drawable drawable) {
		if (drawable == null) {
			throw new IllegalArgumentException("Drawable cannot be null.");
		}
		mFootDivider = drawable;
	}

	/**
	 * Sets the {@link Drawable} for the divider of horizontal and vertical.
	 *
	 * @param drawable Drawable that should be used as a divider.
	 */
	public void setDrawable(@NonNull Drawable drawable) {
		setHorizontalDrawable(drawable);
		setVerticalDrawable(drawable);
	}

	/**
	 * Sets the {@link Drawable} for the divider of horizontal.
	 *
	 * @param drawable Drawable that should be used as a divider.
	 */
	public void setHorizontalDrawable(@NonNull Drawable drawable) {
		if (drawable == null) {
			throw new IllegalArgumentException("Drawable cannot be null.");
		}
		mHorizontalDivider = drawable;
	}

	/**
	 * Sets the {@link Drawable} for the divider of vertical.
	 *
	 * @param drawable Drawable that should be used as a divider.
	 */
	public void setVerticalDrawable(@NonNull Drawable drawable) {
		if (drawable == null) {
			throw new IllegalArgumentException("Drawable cannot be null.");
		}
		mVerticalDivider = drawable;
	}

	/**
	 * Sets the number of spans to be laid out.
	 * <p>
	 * If {@link #mOrientation} is {@link #VERTICAL}, this is the number of columns.
	 * If {@link #mOrientation} is {@link #HORIZONTAL}, this is the number of rows.
	 *
	 * @param spanCount The total number of spans in the grid
	 */
	public void setSpanCount(int spanCount) {
		this.spanCount = spanCount;
	}

	@Override
	public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
		if (parent.getLayoutManager() == null) {
			return;
		}
		c.save();

		final int childCount = parent.getChildCount();
//		final int footIndex = (childCount - 1) / spanCount;
		for (int i = 0; i < childCount; i++) {
			final View child = parent.getChildAt(i);
			parent.getDecoratedBoundsWithMargins(child, mBounds);

			int m = i % spanCount;
			int n = i / spanCount;

			if (mOrientation == VERTICAL) {
				if (m != 0) {
					drawHorizontal(c, child, mBounds, mHorizontalDivider);
				}
				if (n != 0) {
					drawVertical(c, child, mBounds, mVerticalDivider);
				}
//				else {
//					if (mHeadDivider != null) {//最顶端间隔
//						drawVertical(c, child, mBounds, mHeadDivider);
//					}
//				}
			} else {
				if (m != 0) {
					drawVertical(c, child, mBounds, mVerticalDivider);
				}
				if (n != 0) {
					drawHorizontal(c, child, mBounds, mHorizontalDivider);
				}

			}
		}
		c.restore();
	}

	private void drawHorizontal(Canvas canvas, View item, Rect itemBounds, Drawable divider) {
		final int left = itemBounds.left + Math.round(ViewCompat.getTranslationX(item));
		final int right = left + divider.getIntrinsicWidth();
		final int bottom = itemBounds.bottom + Math.round(ViewCompat.getTranslationY(item))
				- item.getHeight() / 2 + divider.getIntrinsicHeight() / 2;
		final int top = bottom - divider.getIntrinsicHeight();
		divider.setBounds(left, top, right, bottom);
		divider.draw(canvas);
	}

	private void drawVertical(Canvas canvas, View item, Rect itemBounds, Drawable divider) {
		final int top = itemBounds.top + Math.round(ViewCompat.getTranslationY(item));
		final int bottom = top + divider.getIntrinsicHeight();
		final int right = itemBounds.right + Math.round(ViewCompat.getTranslationX(item))
				- item.getWidth() / 2 + divider.getIntrinsicWidth() / 2;
		final int left = right - divider.getIntrinsicWidth();
		divider.setBounds(left, top, right, bottom);
		divider.draw(canvas);
	}



	@Override
	public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
		int position = parent.getChildLayoutPosition(view);

		int m = position % spanCount;
		int n = position / spanCount;

		//默认先给所有Item加上左边距和上边距
		outRect.set(mHorizontalDivider.getIntrinsicWidth(), mVerticalDivider.getIntrinsicHeight(), 0, 0);

		if (mOrientation == VERTICAL) {
			if (m == 0) {//最左边一列，去掉左边距
				outRect.left = 0;
			}
			if (n == 0) {//最上面一行，去掉上边距
				outRect.top = 0;
			}
		} else {
			if (m == 0) {//最上面一行，去掉上边距
				outRect.top = 0;
			}
			if (n == 0) {//最左边一列，去掉左边距
				outRect.left = 0;
			}
		}
	}
}
